#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   EOL.py
@Time    :   2023/06/16 13:31:28
@Author  :   YangLiang 
@Version :   1.0
@Contact :   YangLiang@chengtech.com
@License :   (C)Copyright 2022-2025
@Desc    :   None
'''

# here put the import lib
from pytest_assume.plugin import assume
 
import pytest
import pandas
import logging
import time
# from sympy import assuming
from commDriver.TS_CAN import *
import allure
import sys
import Set_up

sys.dont_write_bytecode = True

target_Position_LF = [0x48,0x6C,0xD4,0xC0]
target_Position_LR = [0x46,0x50,0x33,0x00]
target_Position_RF = [0x48,0x6C,0xD4,0xC0]
target_Position_RR = [0x52,0x08,0x33,0x00]

class Test_EOL():


    def enter_extended(self,Driver,iStep):
        with allure.step(f"Step{iStep}:Request:0x10 0x03, # Response:0x50,0x03"):
            uds_rep,size = Driver.req_and_res_can([0x10,0x03],2)
            if  uds_rep[0:2] != [0x50,0x03]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')  
                logging.error(f'correct response:[0x50,0x03], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:2] == [0x50,0x03]
            iStep += 1
        return iStep
    
    def tester_present(self,Driver,iStep):
        with allure.step(f"Step{iStep}:Request:3E 80, # Response:no response"):
            uds_rep,size = Driver.req_and_res_can([0x3E,0x00],2)
            iStep += 1
        return iStep

    def securityAccess(self,Driver,driver,iStep):
        seed1 = []
        
        with allure.step(f"Step{iStep}:Request:0x27,0x01, # Response:0x67,0x01"):
            uds_rep,size = driver.req_and_res_can([0x27,0x01],2)
            if  uds_rep[0:2] != [0x67,0x01]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')  
                logging.error(f'correct response:[0x67,0x01], actual response:[{actuRespStr}]')
            with assume: assert (uds_rep[0:2] == [0x67,0x01] and size == 18)
            seed1 = uds_rep[2:]
        
            key = Driver['CAN'].calcKey(seed1)
            send_key = [0x27,0x02] + key
            iStep += 1
        with allure.step(f"Step{iStep}:Request:{0}, # Response:0x67,0x02".format(send_key)):
            uds_rep,size = driver.req_and_res_can(send_key,len(send_key))
            if  uds_rep[0:2] != [0x67,0x02]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')  
                correct_send_key = binascii.b2a_hex(bytearray(send_key), ' ')  
                logging.error(f'correct response:[{correct_send_key}], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:2] == [0x67,0x02]
            iStep += 1
        return iStep

    def SWnumber(self,Driver,iStep):   
        with allure.step(f"Step{iStep}:Request:0x22,0xF1,0x95, # Response:0x62,0xF1,0x95+{0}".format(Set_up.ECUSoftwareversionnumber)):
            uds_rep,datasize = Driver.req_and_res_can([0x22,0xF1,0x95],3)
            if  uds_rep[3:] != Set_up.ECUSoftwareversionnumber:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                corretc_RespStr = binascii.b2a_hex(bytearray(Set_up.ECUSoftwareversionnumber), ' ') 
                logging.error(f'correct response:[[0x62,0xF1,0x95] + {corretc_RespStr}], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:12] == [0x62,0xF1,0x95] + Set_up.ECUSoftwareversionnumber
            iStep += 1
        return iStep

    def target_Position_write(self,Driver,drive,iStep):
        if drive == Driver['UDSLRCR']:
            with allure.step(f"Step{iStep}:Request:0x2E,0x12,0x66,{target_Position_LR}, # Response:0x6E,0x12,0x66"):
                uds_rep,datasize = drive.req_and_res_can([0x2E,0x12,0x66]+target_Position_LR,7)
                if  uds_rep[0:3] != [0x6E,0x12,0x66]:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                    logging.error(f'correct response:[0x6E,0x12,0x66] , actual response:[{actuRespStr}]')
                with assume: assert uds_rep[0:3] == [0x6E,0x12,0x66]
            iStep += 1
    
        if drive == Driver['UDSRRCR']:
            with allure.step(f"Step{iStep}:Request:0x2E,0x12,0x66,{target_Position_RR}, # Response:0x6E,0x12,0x66"):
                uds_rep,datasize = drive.req_and_res_can([0x2E,0x12,0x66]+target_Position_RR,7)
                if  uds_rep[0:3] != [0x6E,0x12,0x66]:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                    logging.error(f'correct response:[0x6E,0x12,0x66] , actual response:[{actuRespStr}]')
                with assume: assert uds_rep[0:3] == [0x6E,0x12,0x66]
            iStep += 1
        return iStep

    def target_Position_Read(self,Driver,drive,iStep):
        if drive == Driver['UDSLRCR']:
            with allure.step(f"Step{iStep}:Request:0x22,0x12,0x66, # Response:0x62,0x12,0x66,{target_Position_LR}"):
                uds_rep,datasize = drive.req_and_res_can([0x22,0x12,0x66],3)
                if  uds_rep[0:7] != [0x62,0x12,0x66] + target_Position_LR:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')
                    excRespStr = binascii.b2a_hex(bytearray(target_Position_LR), ' ')
                    logging.error(f'correct response:[0x62,0x12,0x66]+{excRespStr}, actual response:[repair {actuRespStr}]')
                with assume: assert uds_rep[0:7] == [0x62,0x12,0x66] + target_Position_LR
            iStep += 1

        

        if drive == Driver['UDSRRCR']:
            with allure.step(f"Step{iStep}:Request:0x22,0x12,0x66, # Response:0x62,0x12,0x66,{target_Position_RR}"):
                uds_rep,datasize = drive.req_and_res_can([0x22,0x12,0x66],3)
                if  uds_rep[0:7] != [0x62,0x12,0x66] + target_Position_RR:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ')
                    excRespStr = binascii.b2a_hex(bytearray(target_Position_RR), ' ')
                    logging.error(f'correct response:[0x62,0x12,0x66]+{excRespStr}, actual response:[repair {actuRespStr}]')
                with assume: assert uds_rep[0:7] == [0x62,0x12,0x66] + target_Position_RR
            iStep += 1
        return iStep

    def clear_DTC(self,Driver,iStep):
        with allure.step(f"Step{iStep}:Request:0x14,0xFF,0xFF,0xFF, # Response:0x54"):
            uds_rep,size = Driver.req_and_res_can([0x14,0xFF,0xFF,0xFF],4)
            if  uds_rep[0] != 0x54:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                logging.error(f'correct response:[0x54], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0] == 0x54
            time.sleep(1)
            iStep += 1
        return iStep

    def read_DTC(self,Driver,iStep,Current=True):
        if Current:
            #在标定前会存在“标定未完成”的故障[98 7c 54]
            with allure.step(f"Step{iStep}:Request:0x19,0x02,0x09, # Response:0x19,0x02,0x09,0x98,0x7c,0x54,0x09"):
                uds_rep,size = Driver.req_and_res_can([0x19,0x02,0x09],3)
                if  uds_rep[0:3] != [0x59,0x02,0x09]:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                    logging.error(f'correct response:[0x59,0x02,0x09,0x98,0x7c,0x54,0x09], actual response:[{actuRespStr}]')
                with assume: assert uds_rep[0:3] == [0x59,0x02,0x09]
                iStep += 1
        else:
            with allure.step(f"Step{iStep}:Request:0x19,0x02,0x09, # Response:0x19,0x02,0x09"):
                uds_rep,size = Driver.req_and_res_can([0x19,0x02,0x09],3)
                # if size != 3:
                #     actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                #     logging.error(f'correct response:[0x59,0x02,0x09], actual response:[repair:{actuRespStr}]')
                #     logging.error(f'correct size:3, actual response:[repair:{size}]')
                # with assume: assert uds_rep[0:3] == [0x59,0x02,0x09]

                if  uds_rep[0:3] != [0x59,0x02,0x09]:
                    actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                    logging.error(f'correct response:[0x59,0x02,0x09], actual response:[repair:{actuRespStr}]')
                with assume: assert uds_rep[0:3] == [0x59,0x02,0x09]
                iStep += 1
        return iStep

    def rounting(self,Driver,iStep):
                #Start EOL
        # X1 表示例程状态 
        # 0x01=Routine start successfully
        # 0x02=Routine start unsuccessfully
        # 0x03 = Routine in progress
        # 0x04=Routine Completed successfully
        # 0x05=Routine Completed unsuccessfully
        with allure.step(f"Step{iStep}:Request:0x31,0x01,0x12,0x7A, # Response:71 01 12 7A X1"):
            uds_rep,size = Driver.req_and_res_can([0x31,0x01,0x12,0x7A],4)
            if  uds_rep[0:4] != [0x71,0x01,0x12,0x7A]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                logging.error(f'correct response:[0x71,0x01,0x12,0x7A,0xX1], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:4]== [0x71,0x01,0x12,0x7A]
            time.sleep(2)
            iStep += 1
        # Request for EOL result
        with allure.step(f"Step{iStep}:Request:0x31,0x03,0x12,0x7A, # Response:71 03 12 7A X1 X2 X3 X4 X5 X6 X7 X8 X9"):
            uds_rep,size = Driver.req_and_res_can([0x31,0x03,0x12,0x7A],4)
            with assume: assert size == 13
            if  uds_rep[0:4] != [0x71,0x03,0x12,0x7A]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                logging.error(f'correct response:[71 03 12 7A X1 X2 X3 X4 X5 X6 X7 X8 X9], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:4]== [0x71,0x03,0x12,0x7A]
            iStep += 1
        return uds_rep,iStep

    def stop_RID(self,Driver,iStep):
        # Stop EOL
        # X1 表示例程状态
        # 0x01=Routine start successfully
        # 0x02=Routine start unsuccessfully
        # 03 = Routine in progress
        # 04=Routine Completed successfully
        # 05=Routine Completed unsuccessfully
        with allure.step(f"Step{iStep}:Request:0x31,0x02,0x12,0x7A, # Response:71 02 12 7A X1"):
            uds_rep,size = Driver.req_and_res_can([0x31,0x02,0x12,0x7A],4)
            with assume: assert size == 5
            if  uds_rep[0:4] != [0x71,0x02,0x12,0x7A]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                logging.error(f'correct response:[71 02 12 7A X1], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:4]== [0x71,0x02,0x12,0x7A]
            iStep += 1
        return iStep

    def resetDUT(self,Driver,iStep):
        with allure.step(f"Step{iStep}:Request:0x11,0x01, # Response:0x51,0x01"):
            uds_rep,size = Driver.req_and_res_can([0x11,0x01],2)
            if  uds_rep[0:2] != [0x51,0x01]:
                actuRespStr = binascii.b2a_hex(bytearray(uds_rep), ' ') 
                logging.error(f'correct response:[0x51,0x01], actual response:[{actuRespStr}]')
            with assume: assert uds_rep[0:2] == [0x51,0x01]
            time.sleep(4)
            iStep += 1
        return iStep

    @pytest.mark.repeat(100)
    @allure.severity('normal')
    @allure.description("EOL flow test")
    def test_flow(self,Driver,action):
        driver_UDS = [Driver['UDSLRCR'],Driver['UDSRRCR']]
        iStep = 1
        for drive in driver_UDS :
            iStep = self.enter_extended(drive,iStep)
        for drive in driver_UDS :
            iStep = self.tester_present(drive,iStep)
        for drive in driver_UDS :    
            iStep = self.securityAccess(Driver,drive,iStep)
        for drive in driver_UDS :
            iStep = self.SWnumber(drive,iStep)
        for drive in driver_UDS :
            iStep = self.target_Position_write(Driver,drive,iStep)
        for drive in driver_UDS :
            iStep = self.target_Position_Read(Driver,drive,iStep)
        for drive in driver_UDS :
            iStep = self.clear_DTC(drive,iStep)
        for drive in driver_UDS :
            iStep = self.read_DTC(drive,iStep)
        for drive in driver_UDS :
            for can in driver_UDS :
                iStep = self.tester_present(can,iStep)
            uds_rep,iStep = self.rounting(drive,iStep)
            if uds_rep[9] != 7: #没有反射板，静态标定失败
                uds_rep,iStep = self.rounting(drive,iStep)
                logging.info(f'repair and Routine Running Status uds_rep[9]:{uds_rep[9]}')
                if uds_rep[9] != 7:
                    uds_rep,iStep = self.rounting(drive,iStep)
                    logging.info(f'repair and Routine Running Status uds_rep[9]:{uds_rep[9]}')
                    if uds_rep[9] != 7:
                        # with assume:assert 1 == 0
                        logging.info(f'repair and Routine Running Status uds_rep[9]:{uds_rep[9]}')
                    else:
                        logging.info('Third calibration pass')
                else:
                        logging.info('Second calibration pass')
            else:
                        logging.info('First calibration pass')
        for drive in driver_UDS :
            iStep = self.stop_RID(drive,iStep)
        for drive in driver_UDS :
            iStep =  self.clear_DTC(drive,iStep)
        for drive in driver_UDS :
            iStep = self.read_DTC(drive,iStep,False)
        for drive in driver_UDS :
            iStep = self.resetDUT(drive,iStep)









    def get_frame(self,Driver,Front = True):
        if Front:
            Driver['CAN2'].fush_q_buff()
            time.sleep(2)
            ALl_data, buffer_size = Driver['CAN2'].read_frame()
            PCAN_Data_L = ALl_data[ALl_data['AIdentifier']==0x20A]
            PCAN_Data_fsp_L = Driver['CAN2'].get_fps(0x20A,'CANFD')
            PCAN_Data_R = ALl_data[ALl_data['AIdentifier']==0x240]
            PCAN_Data_fsp_R = Driver['CAN2'].get_fps(0x240,'CANFD')
        else:
            Driver['CAN2'].fush_q_buff()
            time.sleep(2)
            ALl_data, buffer_size = Driver['CAN2'].read_frame()
            PCAN_Data_L = ALl_data[ALl_data['AIdentifier']==0x28A]
            PCAN_Data_fsp_L = Driver['CAN2'].get_fps(0x28A,'CANFD')
            PCAN_Data_R = ALl_data[ALl_data['AIdentifier']==0x2C0]
            PCAN_Data_fsp_R = Driver['CAN2'].get_fps(0x2C0,'CANFD')
        return PCAN_Data_L,PCAN_Data_fsp_L,PCAN_Data_R,PCAN_Data_fsp_R


    def extend_session(self,Driver):
        uds_rep,size = Driver['UDS'].req_and_res_can([0x10,0x03],2)
        with assume: assert uds_rep[0:2] == [0x50,0x03]

    def get_app_fsp(self,Driver):
        Radar_APP_message_fsp_RR1 = Driver['CAN'].get_fps(0x44c,'CANFD')  # app CAN1
        Radar_APP_message_fsp_RR2 = Driver['CAN'].get_fps(0x449,'CANFD')
        Radar_APP_message_fsp_FR = Driver['CAN'].get_fps(0x224,'CANFD')
        # v,i =Driver['power'].Read_Measure()
        # sleepmode = True if ( i < 0.08) else False   #开机fsp返回-1
        sleepmodeRR1 = True if ((Radar_APP_message_fsp_RR1 == 0 or Radar_APP_message_fsp_RR1 == -1 )) else False   #开机fsp返回-1
        sleepmodeRR2 = True if ((Radar_APP_message_fsp_RR2 == 0 or Radar_APP_message_fsp_RR2 == -1 )) else False
        sleepmodeFR = True if ((Radar_APP_message_fsp_FR == 0 or Radar_APP_message_fsp_FR == -1 )) else False
        with assume: assert sleepmodeRR1 == True
        with assume: assert sleepmodeRR2 == True
        with assume: assert sleepmodeFR == True
        return sleepmodeRR1,sleepmodeRR2,sleepmodeFR

    def get_app_fsp_local(self,Driver):
        # Radar_APP_message_fsp_RR1 = Driver['CAN'].get_fps(0x385,'CANFD')  # app CAN1
        # Radar_APP_message_fsp_RR2 = Driver['CAN'].get_fps(0x386,'CANFD')
        Radar_APP_message_fsp_FR = Driver['CAN'].get_fps(0x224,'CANFD')
        # v,i =Driver['power'].Read_Measure()
        # sleepmode = True if ( i < 0.08) else False   #开机fsp返回-1
        # sleepmodeRR1 = True if ((Radar_APP_message_fsp_RR1 == 0 or Radar_APP_message_fsp_RR1 == -1 )) else False   #开机fsp返回-1
        # sleepmodeRR2 = True if ((Radar_APP_message_fsp_RR2 == 0 or Radar_APP_message_fsp_RR2 == -1 )) else False
        if ((Radar_APP_message_fsp_FR == 0 or Radar_APP_message_fsp_FR == -1 )):
            sleepmodeFR = True
        else:
            sleepmodeFR = False
        # with assume: assert sleepmodeRR1 == True
        # with assume: assert sleepmodeRR2 == True
        # with assume: assert sleepmodeFR == True
        # return sleepmodeRR1,sleepmodeRR2,sleepmodeFR
        return sleepmodeFR


    @pytest.mark.repeat(2)  #计划跑100cycle
    def test_cycle_wakeup_two_CR(self,Driver, power_reset):      #BUSSLEEP_WAKEUP_FLASH 
        logging.info('test start!')
        Driver['CAN'].wakeup_ctrl(False)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrMod',0)
        time.sleep(0.5)
        # 门锁状态 1-lock 2-unlock
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','DrvrDoorLockStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','PassDoorLockStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReLeDoorLockStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReRiDoorLockStsSwt',2)
        # 车门状态 1-close 2-open
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','DrvrDoorOpenStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','PassDoorOpenStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReLeDoorOpenStsSwt',2)
        Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReRiDoorOpenStsSwt',2)
        time.sleep(10)
        sleepmodeFR = True
        start_time = time.time()
        while( (time.time()-start_time) < 3):
            sleepmodeFR = self.get_app_fsp_local(Driver)
            if sleepmodeFR:
                logging.info(f'PASSED:wait for all CR enter to sleepmode if all True:0x224_{sleepmodeFR}')
                break
            time.sleep(0.1)
        if sleepmodeFR:
            Driver['CAN'].fush_q_buff()
            time.sleep(1)
            Driver['CAN'].wakeup_ctrl(True)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'PEPS_0x1B1','PwrMod',2)
            time.sleep(0.5)
            # 门锁状态 1-lock 2-unlock
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','DrvrDoorLockStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','PassDoorLockStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReLeDoorLockStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReRiDoorLockStsSwt',1)
            # 车门状态 1-close 2-open
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','DrvrDoorOpenStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','PassDoorOpenStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReLeDoorOpenStsSwt',1)
            Driver['CAN'].write_db_signal(Set_up.NetName,Set_up.nodeName,'BCM_0x2F1','ReRiDoorOpenStsSwt',1)
            time.sleep(8)
            self.extend_session(Driver)
            sleepmodeFR = self.get_app_fsp_local(Driver)
            if not sleepmodeFR:
                logging.info(f'PASSED:CR is wakeup if False:0x224_{sleepmodeFR}')
            else:
                with assume: assert 1 == 0
                logging.error(f'FAILED:CR is wakeup if False:0x224_{sleepmodeFR}')

            datas_L,fsp_L,datas_R,fsp_R = self.get_frame(Driver,Front = False)
            # logging.info('datas is empty? :{}'.format(datas.empty))
            with assume: assert 15 <= fsp_L <= 25
            with assume: assert 15 <= fsp_R <= 25
            with assume: assert datas_L.empty == False
            with assume: assert datas_R.empty == False
            logging.info(f'Rear: fram fsp_L :{fsp_L},fram fsp_R :{fsp_R}')
            # datas_L,fsp_L,datas_R,fsp_R = self.get_frame(Driver,Front = True)
            # with assume: assert 15 <= fsp_L <= 25
            # with assume: assert 15 <= fsp_R <= 25
            # with assume: assert datas_L.empty == False
            # with assume: assert datas_R.empty == False
            # logging.info(f'Front:fram fsp_L :{fsp_L},fram fsp_R :{fsp_R}')
        else:
            logging.info('Not sleep!')
            with assume: assert 1 == 0
            
        logging.info('test end!')